package com.zxy.supplier_system.server.repository

import com.zxy.supplier_system.server.controller.MarketsGoodsController
import com.zxy.supplier_system.server.entity.Employee
import com.zxy.supplier_system.server.entity.Goods
import com.zxy.supplier_system.server.entity.Market
import com.zxy.supplier_system.server.entity.MarketGoods
import com.zxy.supplier_system.server.utils.joinOnce
import jakarta.persistence.criteria.From
import jakarta.persistence.criteria.Root
import org.springframework.data.jpa.domain.Specification
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.JpaSpecificationExecutor

interface MarketGoodsRepository : JpaRepository<MarketGoods, MarketGoods.UnionId>,
    JpaSpecificationExecutor<MarketGoods> {

    object Specifications {

        fun byCondition(queryMarketGoodsRequest: MarketsGoodsController.QueryMarketGoodsRequest): Specification<MarketGoods> {
            val goodsPathBuilder: (root: Root<MarketGoods>) -> From<MarketGoods, Goods> =
                { root -> root.joinOnce<MarketGoods, Goods>("goods") }
            return Specification.allOf(
                GoodsRepository.Specifications.brandIn(
                    queryMarketGoodsRequest.brandIds,
                    goodsPathBuilder
                ),
                GoodsRepository.Specifications.categoryIn(queryMarketGoodsRequest.categoryIds, goodsPathBuilder),
                GoodsRepository.Specifications.factoryIn(queryMarketGoodsRequest.factoryIds, goodsPathBuilder),
                GoodsRepository.Specifications.nameContains(queryMarketGoodsRequest.name, goodsPathBuilder),
                GoodsRepository.Specifications.barcodeContains(queryMarketGoodsRequest.barcode, goodsPathBuilder),
                Specification.anyOf(
                    GoodsRepository.Specifications.nameContains(queryMarketGoodsRequest.name, goodsPathBuilder),
                    GoodsRepository.Specifications.barcodeContains(queryMarketGoodsRequest.barcode, goodsPathBuilder),
                ),
            )
        }

        fun marketIdEqual(marketId: Int): Specification<MarketGoods> {
            return Specification { root, query, criteriaBuilder ->
                criteriaBuilder.equal(
                    root.joinOnce<MarketGoods, Market>("market").get<Int>("id"),
                    marketId
                )
            }
        }


        fun ifUCanSee(employee: Employee): Specification<MarketGoods>? {
            return Specification { root, query, criteriaBuilder ->
                MarketRepository.Specifications.ifICanSee(
                    root.joinOnce<MarketGoods, Market>("market"),
                    criteriaBuilder,
                    query,
                    employee
                )
            }
        }


    }

}
